unit RdClasses;

interface

uses
  Windows, Classes, RclLog, RdIntfs, LogLab;

type
  TRdInterfacedObject = class(TObject, IInterface, IRdInterface)
  private
    FRefCount: Integer;
  protected
    FOwned: Boolean;
    { IInterface }
    function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
    { IRdInterface }
    function toString: string; virtual; stdcall;
    function Implementor: TObject; stdcall;
  public
    constructor Create(Owned: Boolean); overload; virtual;
    constructor Create; overload; virtual;
  end;

type
  TRdInterfacedPersistent = class(TPersistent, IInterface, IRdInterface)
  private
    FRefCount: Integer;
    FClassName: string;
  protected
    FOwned: Boolean;
    { IInterface }
    function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
    { IRdInterface }
    function toString: string; virtual; stdcall;
    function Implementor: TObject; stdcall;
  public
    constructor Create(Owned: Boolean); overload; virtual;
    constructor Create; overload; virtual;
  end;

type
  TRdLogPersistent = class(TRdInterfacedPersistent)
  protected
    FLog: ILog;
  public
    constructor Create(Owned: Boolean); override;

    property Log: ILog read FLog;
  end;

  TRdLogObject = class(TRdInterfacedObject)
  protected
    FLog: ILog;
  public
    constructor Create(Owned: Boolean); override;
    property Log: ILog read FLog;
  end;

  TRdLogPersistentClass = class of TRdLogPersistent;

implementation

constructor TRdInterfacedObject.Create;
begin
  Create(False);
end;

function TRdInterfacedObject.Implementor: TObject;
begin
  Result := Self;
end;

{ TRdInterfacedObject }

constructor TRdInterfacedObject.Create(Owned: Boolean);
begin
  FOwned := Owned;
end;

function TRdInterfacedObject.QueryInterface(const IID: TGUID;
  out Obj): HResult;
const
  E_NOINTERFACE = HResult($80004002);
begin
  if GetInterface(IID, Obj) then
    Result := 0
  else
    Result := E_NOINTERFACE;
end;

function TRdInterfacedObject.toString: string;
begin
  Result := Self.ClassName;
end;

function TRdInterfacedObject._AddRef: Integer;
begin
  Result := InterlockedIncrement(FRefCount)
end;

function TRdInterfacedObject._Release: Integer;
begin
  Result := InterlockedDecrement(FRefCount);
  if Result = 0 then
    if FOwned then
      Destroy;
end;

constructor TRdInterfacedPersistent.Create;
begin
  Create(False);  
end;

function TRdInterfacedPersistent.Implementor: TObject;
begin
  Result := Self;
end;

{ TRdInterfacedPersistent }

constructor TRdInterfacedPersistent.Create(Owned: Boolean);
begin
  FOwned := Owned;
  FRefCount := 0;
  FClassName := Self.ClassName;
end;

function TRdInterfacedPersistent.QueryInterface(const IID: TGUID;
  out Obj): HResult;
const
  E_NOINTERFACE = HResult($80004002);
begin
  if GetInterface(IID, Obj) then
    Result := 0
  else
    Result := E_NOINTERFACE;
end;

function TRdInterfacedPersistent.toString: string;
begin
  Result := Self.ClassName;
end;

function TRdInterfacedPersistent._AddRef: Integer;
begin
  Result := InterlockedIncrement(FRefCount);
end;

function TRdInterfacedPersistent._Release: Integer;
begin
  Result := InterlockedDecrement(FRefCount);
  if Result = 0 then
    if FOwned then
      Destroy;
end;

{ TRdInterfacedPersistent }

constructor TRdLogPersistent.Create(Owned: Boolean);
begin
  inherited Create(Owned);
  FLog := RclLog.GetLogVendor.GetLog(Self);
end;

{ TRdInterfacedPersistent }

constructor TRdLogObject.Create(Owned: Boolean);
begin
  inherited Create(Owned);
  FLog := RclLog.GetLogVendor.GetLog(Self);
end;

end.
